home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Over 1,000 Windows 95 Programs
/
Over 1000 Windows 95 Programs (Microforum) (Disc 1).iso
/
0769
/
finger.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-04-10
|
20KB
|
647 lines
//
// Finger Version 3.1, a Windows Sockets Finger Client
//
// Copyright 1992, 1993 Network Research Corporation
//
// Permission to use, modify, and distribute this software and its
// documentation for any purpose and without fee is hereby granted, provided
// that the above copyright notice appears in all copies and that both
// that copyright notice and this permission notice appear in supporting
// documentation. NRC makes no claims as to the suitability of this software
// for any purpose.
//
// Module FINGER provides the user interface for the finger client, and
// depends on NETWRK for TCP/IP network services, and upon DSPLIST
// retrieve and dispose of "display lists". The display list represents
// the remote finger server's return in a form suitable for scrolling text
// display. FINGER prompts the user for a host name (or internet address),
// invokes NETWRK to finger the specified host, and paints the window
// client area with the returned display list. FINGER uses a view
// (a logical window onto a portion of the display list) to render
// that portion of the list which is currently visable.
//
// 02/12/92 Lee Murach Created.
// 06/19/92 Mark Towfiq Adapted to Windows Socket draft rev 1.0.
// 09/25/92 Ian Merritt Adapted for Windows Sockets 1.0B compatability.
// 10/20/92 Lee Murach Restructured (Ray Duncan-ized) & added scrollbars.
// 12/02/92 Lee Murach Split FingerHost() into FingerStart() &
// FingerFinish(), for NETWORK_ module interface.
// 03/25/93 Lee Murach Added per-user finger support.
//
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <winsock.h>
#include "finger.h"
#define MAXTEXT 132
#define THUMBPOS LOWORD(lParam) // Win 16
typedef struct // associates an error code with text
{
UINT err;
char *sztext;
} ERRENTRY;
int APIENTRY WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
LONG FAR APIENTRY FrameWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
BOOL APIENTRY HostDlgProc(HWND hDlg, UINT wMsg, UINT wParam, LONG lParam);
BOOL FAR APIENTRY AboutDlgProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
BOOL InitInstance(HANDLE hInstance, int nCmdShow);
BOOL InitApp(HANDLE hInstance);
LONG DoPaint(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoSize(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoCommand(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoDestroy(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoMouseMove(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoMenuHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoVScroll(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoActivate(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoClose(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoMenuExit(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoMenuAbout(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
VOID Repaint(VOID);
VOID PosView(int nlines);
VOID ReportWSError(UINT Err);
VOID RelScroll(HWND hWnd, int nlines);
VOID SetWinCaption(VOID);
VOID SetScroll(VOID);
VOID ReportWSError(UINT Err);
char szHostName[MAXHOST+1] = "";// name of host to finger
char szUser[MAXUSER+1] = ""; // query for this user id (can be null)
char szAppName[] = "Finger"; // application's name
LINEITEM *pLineItems = 0; // ptr to display list LINEITEMS
int nLineItems = 0; // number of items in display list
LINEITEM *pTopLine; // pts to topmost displayable LINEITEM
int nTopLine = 0; // line number of topmost displayed line
int nClientLines; // # of text lines in view
int CharY; // pixel character height
HWND hFrame; // finger main window handle
HMENU hMenu; // main window menu handle
HANDLE hInst; // this instance of finger
HCURSOR hCursor; // current cursor (either wait or normal)
WSADATA WSAData; // windows sockets info return
DECODEWORD frameMsgs[] = // windows messages & handlers
{
WM_ACTIVATE, DoActivate,
WM_CLOSE, DoClose,
WM_COMMAND, DoCommand,
WM_DESTROY, DoDestroy,
WM_MOUSEMOVE, DoMouseMove,
WM_PAINT, DoPaint,
WM_SIZE, DoSize,
WM_VSCROLL, DoVScroll,
WM_KEYDOWN, DoVScroll,
};
DECODEWORD menuItems[] = // menu items & associated handlers
{
IDM_HOST, DoMenuHost,
IDM_EXIT, DoMenuExit,
IDM_ABOUT, DoMenuAbout,
};
ERRENTRY wsErrs[] = // error text for windows sockets errors
{
WSAVERNOTSUPPORTED, "This version of Windows Sockets is not supported",
WSASYSNOTREADY, "Windows Sockets is not present or is not responding",
};
ERRENTRY finErrs[] = // finger specific error text
{
FE_NOPORT, "Cannot locate port for finger service",
FE_NOHOST, "Unrecognized host name",
FE_NOSOCK, "Cannot obtain socket for connection",
FE_NOCONN, "Cannot connect to remote server",
FE_NOSEND, "Cannot send query to remote server",
FE_NORECV, "Error occurred during retrieval"
};
//
// WinMain -- windows calls this to start the application.
//
int APIENTRY WinMain(HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg; // holds current message
int err;
hInst = hInstance; // save our instance handle
if (!hPrevInstance) // if first instance,
if (!InitApp(hInstance)) // register window classes
{
MessageBox(hFrame, "Can't initialize Finger", szAppName,
MB_ICONSTOP | MB_OK);
return(FALSE);
}
if (!InitInstance(hInstance, nCmdShow)) // per instance initialization &
{ // window creation
MessageBox(hFrame, "Can't initialize Finger", szAppName,
MB_ICONSTOP | MB_OK);
return(FALSE);
}
if (err = WSAStartup(WSVERSION, &WSAData))// register task with
{ // winsock tcp/ip API
ReportWSError(err);
DestroyWindow(hFrame); // kill application window &
} // signal app exit
while (GetMessage(&msg, NULL, 0, 0)) // loop til WM_QUIT
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
WSACleanup(); // disconnect from winsock
return msg.wParam; // return to windows
}
//
// InitApp -- initialization for all instances of application.
// Registers main window class.
//
BOOL InitApp(HANDLE hInstance)
{
WNDCLASS wndclass;
InitNetApp(); // initializes (per application) network module
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndclass.lpfnWndProc = FrameWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInst, "FingerIcon");
wndclass.hCursor = NULL;
wndclass.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
wndclass.lpszMenuName = "FingerMenu";
wndclass.lpszClassName = szAppName;
return(RegisterClass(&wndclass));
}
//
// InitInstance -- initializes this instance of app, and creates windows.
//
BOOL InitInstance(HANDLE hInstance, int nCmdShow)
{
HDC hdc; // handle of device context
TEXTMETRIC tm; // contains font dimensions
RECT rect; // outer dimensions of window
hFrame = CreateWindow( szAppName, szAppName,
WS_OVERLAPPEDWINDOW | WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
if (!hFrame)
return(FALSE);
hCursor = LoadCursor(NULL, IDC_ARROW);
hMenu = GetMenu(hFrame);
InitNetInst(hFrame); // initialize (per instance) the network module
// finger servers assume a fixed font
hdc = GetDC(hFrame);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hdc, &tm);
CharY = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(hFrame, hdc);
// set initial window width & height to 50x10 chars
GetWindowRect(hFrame, &rect);
MoveWindow( hFrame, rect.left, rect.top,
65 * tm.tmAveCharWidth + GetSystemMetrics(SM_CXVSCROLL),
10 * CharY + GetSystemMetrics(SM_CYCAPTION) +
GetSystemMetrics(SM_CYMENU), FALSE);
ShowWindow(hFrame, nCmdShow);
UpdateWindow(hFrame);
return(TRUE);
}
//
// FrameWndProc -- callback function for application frame (main) window.
// Decodes message and routes to appropriate message handler. If no handler
// found, calls DefWindowProc.
//
LONG FAR APIENTRY FrameWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
int i;
for (i = 0; i < dim(frameMsgs); i++)
{
if (wMsg == frameMsgs[i].Code)
return(*frameMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam);
}
return(DefWindowProc(hWnd, wMsg, wParam, lParam));
}
//
// DoCommand -- demultiplexes WM_COMMAND messages resulting from menu
// selections, and routes to corresponding menu item handler. Sends back
// any unrecognized messages to windows.
//
LONG DoCommand(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
int i;
for (i = 0; i < dim(menuItems); i++)
{
if (wParam == menuItems[i].Code)
return(*menuItems[i].Fxn)(hWnd, wMsg, wParam, lParam);
}
return(DefWindowProc(hWnd, wMsg, wParam, lParam));
}
//
// DoMenuHost -- handles the "Host..." menu item. We prompt for a
// Domain Name System (DNS) host name, or a "dotted IP address" (e.g.,
// 129.216.202.5). The function invokes NETWRK_ module FingerStart()
// routine to initiate a conversation with the finger server on the
// remote host. NETWRK_, in turn, calls FingerFinish() to signal
// completion. Note that the "Host..." menu item is disabled while the
// finger operation is in progress. This prevents the user from
// starting yet another finger before the first is finished; Finger is
// not designed to process simultaneous requests.
//
LONG DoMenuHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
FARPROC lpfnProc;
int ret;
// prompt for the host's domain name or ip address
lpfnProc = MakeProcInstance(HostDlgProc, hInst);
ret = DialogBox(hInst, szAppName, hWnd, lpfnProc);
FreeProcInstance(lpfnProc);
if (ret == IDOK && szHostName[0])
{
SetCursor(hCursor = LoadCursor(NULL, IDC_WAIT));
EnableMenuItem(hMenu, IDM_HOST, MF_GRAYED);
FingerStart();
}
return(FALSE);
}
//
// FingerFinish -- invoked when the finger operation is complete,
// this function updates the display list & repaints the frame window
// client area if the operation was successful.
//
VOID FingerFinish(UINT Err)
{
if (!Err)
{
FreeLineList(pLineItems); // dispose old display
GetDisplayList(&pLineItems, &nLineItems); // list and get new one
SetWinCaption(); // set win title to host name
PosView(0); // position view to top
SetScroll(); // rescale (or delete)
Repaint(); // scrollbar & force a repaint
}
EnableMenuItem(hMenu, IDM_HOST, MF_ENABLED);
SetCursor(hCursor = LoadCursor(NULL, IDC_ARROW));
}
//
// DoMenuExit -- allows close via menu item. Same as sys menu close.
//
LONG DoMenuExit(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
SendMessage(hWnd, WM_CLOSE, 0, 0);
return(FALSE);
}
//
// DoMenuAbout -- respond to "About..." menu selection by invoking the
// "About" dialog box.
//
LONG DoMenuAbout(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
WNDPROC lpProcAbout;
lpProcAbout = MakeProcInstance((WNDPROC)AboutDlgProc, hInst);
DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
FreeProcInstance(lpProcAbout);
return(FALSE);
}
//
// DoDestroy -- posts a WM_QUIT message to the task's win queue, which
// causes the main translate & dispatch loop to exit, and the app to
// terminate.
//
LONG DoDestroy(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
PostQuitMessage(0);
return(FALSE);
}
//
// DoClose -- cleans up display list & tells windows to deallocate
// our window.
//
LONG DoClose(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
FreeLineList(pLineItems);
DestroyWindow(hWnd);
return(FALSE);
}
//
// DoActivate -- grabs the keyboard focus whenever our deminimized window
// is activated. This is so we can respond to VK_HOME, VK_END, etc.
// virtual keys for scrolling. HIWORD(lParam) is TRUE for minimized, while
// LOWORD(wParam) is FALSE for activation message.
//
LONG DoActivate(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
if (!HIWORD(lParam) && LOWORD(wParam))
SetFocus(hFrame);
return FALSE;
}
//
// DoMouseMove -- resets the cursor back to the current cursor (either
// a wait, or normal cursor) because Windows will otherwise redraw it
// using the window's class.
//
LONG DoMouseMove(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
SetCursor(hCursor);
return(FALSE);
}
//
// PosView -- repositions the view relative to the top of the display list.
// The view is a logical "window" onto the display list. The frame window's
// client area is painted with the view's contents.
//
VOID PosView(int nlines)
{
LINEITEM *pline;
int i;
pline = pLineItems; // root of LINEITEM list
for (i = 0; i < nlines; i++)
{
if (!pline)
break;
else
pline = pline->next;
}
pTopLine = pline; // ptr to LINEITEM in topmost view line
nTopLine =+ nlines; // offset of topmost view line
}
//
// DoPaint -- Paint the client area with the contents of the view.
//
LONG DoPaint(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
HDC hdc; // scratch device context
PAINTSTRUCT ps; // scratch paint structure
LINEITEM *pline; // pts to topmost displayable LINEITEM
int i;
pline = pTopLine;
hdc = BeginPaint(hWnd, &ps);
for (i = 0; i <= nClientLines; i++)
{
if (pline)
{
TextOut(hdc, 0, i * CharY, pline->sztext, pline->len);
pline = pline->next;
}
else
break;
}
EndPaint(hWnd, &ps);
return(FALSE);
}
//
// Repaint -- force refresh of client window.
//
VOID Repaint(VOID)
{
InvalidateRect(hFrame, NULL, TRUE);
}
//
// SetScroll -- sets the vertical scroll range to the length of the display
// list. The Scrollbar disappears when the list fits within the view.
//
VOID SetScroll(VOID)
{
if (nLineItems > nClientLines)
SetScrollRange(hFrame, SB_VERT, 0, nLineItems - nClientLines, FALSE);
else
SetScrollRange(hFrame, SB_VERT, 0, 0, FALSE);
SetScrollPos(hFrame, SB_VERT, nTopLine, TRUE);
}
// number of lines below the bottom of the view.
#define NLINESBELOW (nLineItems - nTopLine - nClientLines)
//
// DoVScroll -- process WM_VSCROLL & WM_KEYDOWN for main window.
//
LONG DoVScroll(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
switch (LOWORD(wParam))
{
case VK_HOME:
case SB_TOP:
if (nTopLine > 0)
RelScroll(hWnd, -nTopLine);
break;
case VK_END:
case SB_BOTTOM:
if (NLINESBELOW)
RelScroll(hWnd, NLINESBELOW);
break;
case VK_PRIOR:
case SB_PAGEUP:
if (nTopLine > 0)
RelScroll(hWnd, max(-nClientLines, -nTopLine));
break;
case VK_NEXT:
case SB_PAGEDOWN:
if (NLINESBELOW)
RelScroll(hWnd, min(nClientLines, NLINESBELOW));
break;
case VK_UP:
case SB_LINEUP:
if (nTopLine > 0)
RelScroll(hWnd, -1);
break;
case VK_DOWN:
case SB_LINEDOWN:
if (NLINESBELOW)
RelScroll(hWnd, 1);
break;
case SB_THUMBTRACK:
RelScroll(hWnd, THUMBPOS - nTopLine);
break;
}
SetScrollPos(hFrame, SB_VERT, nTopLine, TRUE);
return(FALSE);
}
//
// RelScroll -- scroll up/down nlines from present position
//
VOID RelScroll(HWND hWnd, int nlines)
{
PosView(nTopLine + nlines);
ScrollWindow(hWnd, 0, -nlines * CharY, NULL, NULL);
UpdateWindow(hWnd);
}
//
// DoSize -- respond to WM_SIZE by recalculating the number of text lines
// in the main window's client area.
//
LONG DoSize(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
nClientLines = HIWORD(lParam) / CharY;
PosView(0);
SetScroll();
return(FALSE);
}
//
// SetWinCaption -- set the frame window caption according to last
// host fingered.
//
VOID SetWinCaption(VOID)
{
char szcaption[80];
strcpy(szcaption, szAppName);
strcat(szcaption, " - ");
strcat(szcaption, szHostName);
SetWindowText(hFrame, szcaption);
}
//
// ReportWSError -- prompt user with a windows sockets error message.
//
VOID ReportWSError(UINT Err)
{
int i;
char szerr[40];
for (i = 0; i < dim(wsErrs); i++)
{
if (Err == wsErrs[i].err)
{
MessageBox(hFrame, wsErrs[i].sztext, szAppName,
MB_ICONSTOP | MB_OK);
return;
}
}
wsprintf(szerr, "Windows Sockets reports error %04x", Err);
MessageBox(hFrame, szerr, szAppName, MB_ICONSTOP | MB_OK);
}
//
// ReportFingerErr -- prompt user with a finger specific error
//
VOID ReportFingerErr(UINT Err)
{
int i;
for (i = 0; i < dim(finErrs); i++)
{
if (Err == finErrs[i].err)
{
MessageBox(hFrame, finErrs[i].sztext, szAppName,
MB_ICONSTOP | MB_OK);
return;
}
}
MessageBox(hFrame, "Unrecognized finger error", szAppName,
MB_ICONSTOP | MB_OK);
}
//
// HostDlgProc -- dialog box proc for "host dialog".
// This box queries user for a host name in response to the user's
// selection of the "Host..." main menu item.
//
BOOL APIENTRY HostDlgProc(HWND hDlg, UINT wMsg, UINT wParam, LONG lParam)
{
switch(wMsg)
{
case WM_INITDIALOG:
SetDlgItemText(hDlg, IDC_HOSTNAME, szHostName);
SetDlgItemText(hDlg, IDC_USER, szUser);
return TRUE;
case WM_COMMAND:
switch(wParam)
{
case IDOK:
GetDlgItemText(hDlg, IDC_HOSTNAME, szHostName, MAXHOST);
GetDlgItemText(hDlg, IDC_USER, szUser, MAXUSER);
EndDialog(hDlg, IDOK);
return TRUE;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
return TRUE;
}
break;
}
return FALSE;
}
//
// AboutDlgProc -- callback for the "About" dialog box
//
BOOL FAR APIENTRY AboutDlgProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
if ((wMsg == WM_COMMAND) && (wParam == IDOK)) // dismiss dialog if OK
EndDialog(hWnd, 0);
return(FALSE); // otherwise just sit there
}